/**
 * pasition v1.0.1 By dntzhang
 * Github: https://github.com/AlloyTeam/pasition
 * MIT Licensed.
 */

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
            (global.pasition = factory());
}(this, (function () { 'use strict';

    var slicedToArray = function () {
        function sliceIterator(arr, i) {
            var _arr = [];
            var _n = true;
            var _d = false;
            var _e = undefined;

            try {
                for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
                    _arr.push(_s.value);

                    if (i && _arr.length === i) break;
                }
            } catch (err) {
                _d = true;
                _e = err;
            } finally {
                try {
                    if (!_n && _i["return"]) _i["return"]();
                } finally {
                    if (_d) throw _e;
                }
            }

            return _arr;
        }

        return function (arr, i) {
            if (Array.isArray(arr)) {
                return arr;
            } else if (Symbol.iterator in Object(arr)) {
                return sliceIterator(arr, i);
            } else {
                throw new TypeError("Invalid attempt to destructure non-iterable instance");
            }
        };
    }();

//https://github.com/colinmeinke/svg-arc-to-cubic-bezier

    var TAU = Math.PI * 2;

    var mapToEllipse = function mapToEllipse(_ref, rx, ry, cosphi, sinphi, centerx, centery) {
        var x = _ref.x,
            y = _ref.y;

        x *= rx;
        y *= ry;

        var xp = cosphi * x - sinphi * y;
        var yp = sinphi * x + cosphi * y;

        return {
            x: xp + centerx,
            y: yp + centery
        };
    };

    var approxUnitArc = function approxUnitArc(ang1, ang2) {
        var a = 4 / 3 * Math.tan(ang2 / 4);

        var x1 = Math.cos(ang1);
        var y1 = Math.sin(ang1);
        var x2 = Math.cos(ang1 + ang2);
        var y2 = Math.sin(ang1 + ang2);

        return [{
            x: x1 - y1 * a,
            y: y1 + x1 * a
        }, {
            x: x2 + y2 * a,
            y: y2 - x2 * a
        }, {
            x: x2,
            y: y2
        }];
    };

    var vectorAngle = function vectorAngle(ux, uy, vx, vy) {
        var sign = ux * vy - uy * vx < 0 ? -1 : 1;
        var umag = Math.sqrt(ux * ux + uy * uy);
        var vmag = Math.sqrt(ux * ux + uy * uy);
        var dot = ux * vx + uy * vy;

        var div = dot / (umag * vmag);

        if (div > 1) {
            div = 1;
        }

        if (div < -1) {
            div = -1;
        }

        return sign * Math.acos(div);
    };

    var getArcCenter = function getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp) {
        var rxsq = Math.pow(rx, 2);
        var rysq = Math.pow(ry, 2);
        var pxpsq = Math.pow(pxp, 2);
        var pypsq = Math.pow(pyp, 2);

        var radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq;

        if (radicant < 0) {
            radicant = 0;
        }

        radicant /= rxsq * pypsq + rysq * pxpsq;
        radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);

        var centerxp = radicant * rx / ry * pyp;
        var centeryp = radicant * -ry / rx * pxp;

        var centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2;
        var centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2;

        var vx1 = (pxp - centerxp) / rx;
        var vy1 = (pyp - centeryp) / ry;
        var vx2 = (-pxp - centerxp) / rx;
        var vy2 = (-pyp - centeryp) / ry;

        var ang1 = vectorAngle(1, 0, vx1, vy1);
        var ang2 = vectorAngle(vx1, vy1, vx2, vy2);

        if (sweepFlag === 0 && ang2 > 0) {
            ang2 -= TAU;
        }

        if (sweepFlag === 1 && ang2 < 0) {
            ang2 += TAU;
        }

        return [centerx, centery, ang1, ang2];
    };

    var arcToBezier = function arcToBezier(_ref2) {
        var px = _ref2.px,
            py = _ref2.py,
            cx = _ref2.cx,
            cy = _ref2.cy,
            rx = _ref2.rx,
            ry = _ref2.ry,
            _ref2$xAxisRotation = _ref2.xAxisRotation,
            xAxisRotation = _ref2$xAxisRotation === undefined ? 0 : _ref2$xAxisRotation,
            _ref2$largeArcFlag = _ref2.largeArcFlag,
            largeArcFlag = _ref2$largeArcFlag === undefined ? 0 : _ref2$largeArcFlag,
            _ref2$sweepFlag = _ref2.sweepFlag,
            sweepFlag = _ref2$sweepFlag === undefined ? 0 : _ref2$sweepFlag;

        var curves = [];

        if (rx === 0 || ry === 0) {
            return [];
        }

        var sinphi = Math.sin(xAxisRotation * TAU / 360);
        var cosphi = Math.cos(xAxisRotation * TAU / 360);

        var pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2;
        var pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2;

        if (pxp === 0 && pyp === 0) {
            return [];
        }

        rx = Math.abs(rx);
        ry = Math.abs(ry);

        var lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);

        if (lambda > 1) {
            rx *= Math.sqrt(lambda);
            ry *= Math.sqrt(lambda);
        }

        var _getArcCenter = getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp),
            _getArcCenter2 = slicedToArray(_getArcCenter, 4),
            centerx = _getArcCenter2[0],
            centery = _getArcCenter2[1],
            ang1 = _getArcCenter2[2],
            ang2 = _getArcCenter2[3];

        var segments = Math.max(Math.ceil(Math.abs(ang2) / (TAU / 4)), 1);

        ang2 /= segments;

        for (var i = 0; i < segments; i++) {
            curves.push(approxUnitArc(ang1, ang2));
            ang1 += ang2;
        }

        return curves.map(function (curve) {
            var _mapToEllipse = mapToEllipse(curve[0], rx, ry, cosphi, sinphi, centerx, centery),
                x1 = _mapToEllipse.x,
                y1 = _mapToEllipse.y;

            var _mapToEllipse2 = mapToEllipse(curve[1], rx, ry, cosphi, sinphi, centerx, centery),
                x2 = _mapToEllipse2.x,
                y2 = _mapToEllipse2.y;

            var _mapToEllipse3 = mapToEllipse(curve[2], rx, ry, cosphi, sinphi, centerx, centery),
                x = _mapToEllipse3.x,
                y = _mapToEllipse3.y;

            return { x1: x1, y1: y1, x2: x2, y2: y2, x: x, y: y };
        });
    };

//https://github.com/jkroso/parse-svg-path/blob/master/index.js
    /**
     * expected argument lengths
     * @type {Object}
     */

    var length = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0

        /**
         * segment pattern
         * @type {RegExp}
         */

    };var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig;

    /**
     * parse an svg path data string. Generates an Array
     * of commands where each command is an Array of the
     * form `[command, arg1, arg2, ...]`
     *
     * @param {String} path
     * @return {Array}
     */

    function parse(path) {
        var data = [];
        path.replace(segment, function (_, command, args) {
            var type = command.toLowerCase();
            args = parseValues(args

                // overloaded moveTo
            );if (type == 'm' && args.length > 2) {
                data.push([command].concat(args.splice(0, 2)));
                type = 'l';
                command = command == 'm' ? 'l' : 'L';
            }

            while (true) {
                if (args.length == length[type]) {
                    args.unshift(command);
                    return data.push(args);
                }
                if (args.length < length[type]) throw new Error('malformed path data');
                data.push([command].concat(args.splice(0, length[type])));
            }
        });
        return data;
    }

    var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig;

    function parseValues(args) {
        var numbers = args.match(number);
        return numbers ? numbers.map(Number) : [];
    }

    function shapeBox(shape) {
        var minX = shape[0][0],
            minY = shape[0][1],
            maxX = minX,
            maxY = minY;
        shape.forEach(function (curve) {
            var x1 = curve[0],
                x2 = curve[2],
                x3 = curve[4],
                x4 = curve[6],
                y1 = curve[1],
                y2 = curve[3],
                y3 = curve[5],
                y4 = curve[7];

            minX = Math.min(minX, x1, x2, x3, x4);
            minY = Math.min(minY, y1, y2, y3, y4);
            maxX = Math.max(maxX, x1, x2, x3, x4);
            maxY = Math.max(maxY, y1, y2, y3, y4);
        });

        return [minX, minY, maxX, maxY];
    }

    function boxDistance(boxA, boxB) {
        return Math.sqrt(Math.pow(boxA[0] - boxB[0], 2) + Math.pow(boxA[1] - boxB[1], 2)) + Math.sqrt(Math.pow(boxA[2] - boxB[2], 2) + Math.pow(boxA[3] - boxB[3], 2));
    }

    function curveDistance(curveA, curveB) {
        var x1 = curveA[0],
            x2 = curveA[2],
            x3 = curveA[4],
            x4 = curveA[6],
            y1 = curveA[1],
            y2 = curveA[3],
            y3 = curveA[5],
            y4 = curveA[7],
            xb1 = curveB[0],
            xb2 = curveB[2],
            xb3 = curveB[4],
            xb4 = curveB[6],
            yb1 = curveB[1],
            yb2 = curveB[3],
            yb3 = curveB[5],
            yb4 = curveB[7];

        return Math.sqrt(Math.pow(xb1 - x1, 2) + Math.pow(yb1 - y1, 2)) + Math.sqrt(Math.pow(xb2 - x2, 2) + Math.pow(yb2 - y2, 2)) + Math.sqrt(Math.pow(xb3 - x3, 2) + Math.pow(yb3 - y3, 2)) + Math.sqrt(Math.pow(xb4 - x4, 2) + Math.pow(yb4 - y4, 2));
    }

    function sortCurves(curvesA, curvesB) {

        var arrList = permuteCurveNum(curvesA.length);

        var list = [];
        arrList.forEach(function (arr) {
            var distance = 0;
            var i = 0;
            arr.forEach(function (index) {
                distance += curveDistance(curvesA[index], curvesB[i++]);
            });
            list.push({ index: arr, distance: distance });
        });

        list.sort(function (a, b) {
            return a.distance - b.distance;
        });

        var result = [];

        list[0].index.forEach(function (index) {
            result.push(curvesA[index]);
        });

        return result;
    }

    function sort(pathA, pathB) {

        var arrList = permuteNum(pathA.length);

        var list = [];
        arrList.forEach(function (arr) {
            var distance = 0;
            arr.forEach(function (index) {
                distance += boxDistance(shapeBox(pathA[index]), shapeBox(pathB[index]));
            });
            list.push({ index: arr, distance: distance });
        });

        list.sort(function (a, b) {
            return a.distance - b.distance;
        });

        var result = [];

        list[0].index.forEach(function (index) {
            result.push(pathA[index]);
        });

        return result;
    }

    function permuteCurveNum(num) {
        var arr = [];

        for (var i = 0; i < num; i++) {
            var indexArr = [];
            for (var j = 0; j < num; j++) {
                var index = j + i;
                if (index > num - 1) index -= num;
                indexArr[index] = j;
            }

            arr.push(indexArr);
        }

        return arr;
    }

    function permuteNum(num) {
        var arr = [];
        for (var i = 0; i < num; i++) {
            arr.push(i);
        }

        return permute(arr);
    }

    function permute(input) {
        var permArr = [],
            usedChars = [];
        function main(input) {
            var i, ch;
            for (i = 0; i < input.length; i++) {
                ch = input.splice(i, 1)[0];
                usedChars.push(ch);
                if (input.length == 0) {
                    permArr.push(usedChars.slice());
                }
                main(input);
                input.splice(i, 0, ch);
                usedChars.pop();
            }
            return permArr;
        }
        return main(input);
    }

    var pasition = {};
    pasition.parser = parse;

    pasition.lerpCurve = function (pathA, pathB, t) {

        return pasition.lerpPoints(pathA[0], pathA[1], pathB[0], pathB[1], t).concat(pasition.lerpPoints(pathA[2], pathA[3], pathB[2], pathB[3], t)).concat(pasition.lerpPoints(pathA[4], pathA[5], pathB[4], pathB[5], t)).concat(pasition.lerpPoints(pathA[6], pathA[7], pathB[6], pathB[7], t));
    };

    pasition.lerpPoints = function (x1, y1, x2, y2, t) {
        return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t];
    };

    pasition.q2b = function (x1, y1, x2, y2, x3, y3) {
        return [x1, y1, (x1 + 2 * x2) / 3, (y1 + 2 * y2) / 3, (x3 + 2 * x2) / 3, (y3 + 2 * y2) / 3, x3, y3];
    };

    pasition.path2shapes = function (path) {
        //https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths
        //M = moveto
        //L = lineto
        //H = horizontal lineto
        //V = vertical lineto
        //C = curveto
        //S = smooth curveto
        //Q = quadratic Belzier curve
        //T = smooth quadratic Belzier curveto
        //A = elliptical Arc
        //Z = closepath
        //以上所有命令均允许小写字母。大写表示绝对定位，小写表示相对定位(从上一个点开始)。
        var cmds = pasition.parser(path),
            preX = 0,
            preY = 0,
            j = 0,
            len = cmds.length,
            shapes = [],
            current = null,
            closeX = void 0,
            closeY = void 0,
            preCX = void 0,
            preCY = void 0,
            sLen = void 0,
            curves = void 0,
            lastCurve = void 0;

        for (; j < len; j++) {
            var item = cmds[j];
            var action = item[0];
            var preItem = cmds[j - 1];

            switch (action) {
                case 'm':
                    sLen = shapes.length;
                    shapes[sLen] = [];
                    current = shapes[sLen];
                    preX = preX + item[1];
                    preY = preY + item[2];
                    break;
                case 'M':

                    sLen = shapes.length;
                    shapes[sLen] = [];
                    current = shapes[sLen];
                    preX = item[1];
                    preY = item[2];
                    break;

                case 'l':
                    current.push([preX, preY, preX, preY, preX, preY, preX + item[1], preY + item[2]]);
                    preX += item[1];
                    preY += item[2];
                    break;

                case 'L':

                    current.push([preX, preY, item[1], item[2], item[1], item[2], item[1], item[2]]);
                    preX = item[1];
                    preY = item[2];

                    break;

                case 'h':

                    current.push([preX, preY, preX, preY, preX, preY, preX + item[1], preY]);
                    preX += item[1];
                    break;

                case 'H':
                    current.push([preX, preY, item[1], preY, item[1], preY, item[1], preY]);
                    preX = item[1];
                    break;

                case 'v':
                    current.push([preX, preY, preX, preY, preX, preY, preX, preY + item[1]]);
                    preY += item[1];
                    break;

                case 'V':
                    current.push([preX, preY, preX, item[1], preX, item[1], preX, item[1]]);
                    preY = item[1];
                    break;

                case 'C':

                    current.push([preX, preY, item[1], item[2], item[3], item[4], item[5], item[6]]);
                    preX = item[5];
                    preY = item[6];
                    break;
                case 'S':
                    if (preItem[0] === 'C' || preItem[0] === 'c') {
                        current.push([preX, preY, preX + preItem[5] - preItem[3], preY + preItem[6] - preItem[4], item[1], item[2], item[3], item[4]]);
                    } else if (preItem[0] === 'S' || preItem[0] === 's') {
                        current.push([preX, preY, preX + preItem[3] - preItem[1], preY + preItem[4] - preItem[2], item[1], item[2], item[3], item[4]]);
                    }
                    preX = item[3];
                    preY = item[4];
                    break;

                case 'c':
                    current.push([preX, preY, preX + item[1], preY + item[2], preX + item[3], preY + item[4], preX + item[5], preY + item[6]]);
                    preX = preX + item[5];
                    preY = preY + item[6];
                    break;
                case 's':
                    if (preItem[0] === 'C' || preItem[0] === 'c') {

                        current.push([preX, preY, preX + preItem[5] - preItem[3], preY + preItem[6] - preItem[4], preX + item[1], preY + item[2], preX + item[3], preY + item[4]]);
                    } else if (preItem[0] === 'S' || preItem[0] === 's') {
                        current.push([preX, preY, preX + preItem[3] - preItem[1], preY + preItem[4] - preItem[2], preX + item[1], preY + item[2], preX + item[3], preY + item[4]]);
                    }

                    preX = preX + item[3];
                    preY = preY + item[4];

                    break;
                case 'a':
                    curves = arcToBezier({
                        rx: item[1],
                        ry: item[2],
                        px: preX,
                        py: preY,
                        xAxisRotation: item[3],
                        largeArcFlag: item[4],
                        sweepFlag: item[5],
                        cx: preX + item[6],
                        cy: preX + item[7]
                    });
                    lastCurve = curves[curves.length - 1];

                    curves.forEach(function (curve, index) {
                        if (index === 0) {
                            current.push([preX, preY, curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y]);
                        } else {
                            current.push([curves[index - 1].x, curves[index - 1].y, curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y]);
                        }
                    });

                    preX = lastCurve.x;
                    preY = lastCurve.y;

                    break;

                case 'A':

                    curves = arcToBezier({
                        rx: item[1],
                        ry: item[2],
                        px: preX,
                        py: preY,
                        xAxisRotation: item[3],
                        largeArcFlag: item[4],
                        sweepFlag: item[5],
                        cx: item[6],
                        cy: item[7]
                    });
                    lastCurve = curves[curves.length - 1];

                    curves.forEach(function (curve, index) {
                        if (index === 0) {
                            current.push([preX, preY, curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y]);
                        } else {
                            current.push([curves[index - 1].x, curves[index - 1].y, curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y]);
                        }
                    });

                    preX = lastCurve.x;
                    preY = lastCurve.y;

                    break;
                case 'Q':
                    current.push(pasition.q2b(preX, preY, item[1], item[2], item[3], item[4]));
                    preX = item[3];
                    preY = item[4];

                    break;
                case 'q':
                    current.push(pasition.q2b(preX, preY, preX + item[1], preY + item[2], item[3] + preX, item[4] + preY));
                    preX += item[3];
                    preY += item[4];
                    break;

                case 'T':

                    if (preItem[0] === 'Q' || preItem[0] === 'q') {
                        preCX = preX + preItem[3] - preItem[1];
                        preCY = preY + preItem[4] - preItem[2];
                        current.push(pasition.q2b(preX, preY, preCX, preCY, item[1], item[2]));
                    } else if (preItem[0] === 'T' || preItem[0] === 't') {
                        current.push(pasition.q2b(preX, preY, preX + preX - preCX, preY + preY - preCY, item[1], item[2]));
                        preCX = preX + preX - preCX;
                        preCY = preY + preY - preCY;
                    }

                    preX = item[1];
                    preY = item[2];
                    break;

                case 't':
                    if (preItem[0] === 'Q' || preItem[0] === 'q') {
                        preCX = preX + preItem[3] - preItem[1];
                        preCY = preY + preItem[4] - preItem[2];
                        current.push(pasition.q2b(preX, preY, preCX, preCY, preX + item[1], preY + item[2]));
                    } else if (preItem[0] === 'T' || preItem[0] === 't') {
                        current.push(pasition.q2b(preX, preY, preX + preX - preCX, preY + preY - preCY, preX + item[1], preY + item[2]));
                        preCX = preX + preX - preCX;
                        preCY = preY + preY - preCY;
                    }

                    preX += item[1];
                    preY += item[2];
                    break;

                case 'Z':
                    closeX = current[0][0];
                    closeY = current[0][1];
                    current.push([preX, preY, closeX, closeY, closeX, closeY, closeX, closeY]);
                    break;
                case 'z':
                    closeX = current[0][0];
                    closeY = current[0][1];
                    current.push([preX, preY, closeX, closeY, closeX, closeY, closeX, closeY]);
                    break;
            }
        }

        return shapes;
    };

    pasition._upCurves = function (curves, count) {
        var i = 0,
            index = 0,
            len = curves.length;
        for (; i < count; i++) {
            curves.push(curves[index].slice(0));
            index++;
            if (index > len - 1) {
                index -= len;
            }
        }
    };

    function split(x1, y1, x2, y2, x3, y3, x4, y4, t) {
        return {
            left: _split(x1, y1, x2, y2, x3, y3, x4, y4, t),
            right: _split(x4, y4, x3, y3, x2, y2, x1, y1, 1 - t, true)
        };
    }

    function _split(x1, y1, x2, y2, x3, y3, x4, y4, t, reverse) {

        var x12 = (x2 - x1) * t + x1;
        var y12 = (y2 - y1) * t + y1;

        var x23 = (x3 - x2) * t + x2;
        var y23 = (y3 - y2) * t + y2;

        var x34 = (x4 - x3) * t + x3;
        var y34 = (y4 - y3) * t + y3;

        var x123 = (x23 - x12) * t + x12;
        var y123 = (y23 - y12) * t + y12;

        var x234 = (x34 - x23) * t + x23;
        var y234 = (y34 - y23) * t + y23;

        var x1234 = (x234 - x123) * t + x123;
        var y1234 = (y234 - y123) * t + y123;

        if (reverse) {
            return [x1234, y1234, x123, y123, x12, y12, x1, y1];
        }
        return [x1, y1, x12, y12, x123, y123, x1234, y1234];
    }

    pasition._splitCurves = function (curves, count) {
        var i = 0,
            index = 0;

        for (; i < count; i++) {
            var curve = curves[index];
            var cs = split(curve[0], curve[1], curve[2], curve[3], curve[4], curve[5], curve[6], curve[7], 0.5);
            curves.splice(index, 1);
            curves.splice(index, 0, cs.left, cs.right);

            index += 2;
            if (index >= curves.length - 1) {
                index = 0;
            }
        }
    };

    pasition._upShapes = function (shapes, count) {
        var _loop = function _loop(i) {
            var shape = shapes[shapes.length - 1];
            var newShape = [];

            shape.forEach(function (curve) {
                newShape.push(curve.slice(0));
            });
            shapes.push(newShape);
        };

        for (var i = 0; i < count; i++) {
            _loop(i);
        }
    };

    pasition._subShapes = function (pathA, pathB, count) {
        var _loop2 = function _loop2(i) {
            var shape = pathB[pathB.length - 1];
            var newShape = [];
            var x = shape[0][0],
                y = shape[0][1];
            shape.forEach(function () {
                newShape.push([x, y, x, y, x, y, x, y]);
            });

            pathB.push(newShape);
        };

        for (var i = 0; i < count; i++) {
            _loop2(i);
        }
    };

    pasition.lerp = function (pathA, pathB, t) {
        return pasition._lerp(pasition.path2shapes(pathA), pasition.path2shapes(pathB), t);
    };

    pasition.MIM_CURVES_COUNT = 100;

    pasition._preprocessing = function (pathA, pathB) {

        var lenA = pathA.length,
            lenB = pathB.length,
            clonePathA = JSON.parse(JSON.stringify(pathA)),
            clonePathB = JSON.parse(JSON.stringify(pathB));

        if (lenA > lenB) {
            pasition._subShapes(clonePathA, clonePathB, lenA - lenB);
        } else if (lenA < lenB) {
            pasition._upShapes(clonePathA, lenB - lenA);
        }

        clonePathA = sort(clonePathA, clonePathB);

        clonePathA.forEach(function (curves, index) {

            var lenA = curves.length,
                lenB = clonePathB[index].length;

            if (lenA > lenB) {
                if (lenA < pasition.MIM_CURVES_COUNT) {
                    pasition._splitCurves(curves, pasition.MIM_CURVES_COUNT - lenA);
                    pasition._splitCurves(clonePathB[index], pasition.MIM_CURVES_COUNT - lenB);
                } else {
                    pasition._splitCurves(clonePathB[index], lenA - lenB);
                }
            } else if (lenA < lenB) {
                if (lenB < pasition.MIM_CURVES_COUNT) {
                    pasition._splitCurves(curves, pasition.MIM_CURVES_COUNT - lenA);
                    pasition._splitCurves(clonePathB[index], pasition.MIM_CURVES_COUNT - lenB);
                } else {
                    pasition._splitCurves(curves, lenB - lenA);
                }
            }
        });

        clonePathA.forEach(function (curves, index) {
            clonePathA[index] = sortCurves(curves, clonePathB[index]);
        });

        return [clonePathA, clonePathB];
    };

    pasition._lerp = function (pathA, pathB, t) {

        var shapes = [];
        pathA.forEach(function (curves, index) {
            var newCurves = [];
            curves.forEach(function (curve, curveIndex) {
                newCurves.push(pasition.lerpCurve(curve, pathB[index][curveIndex], t));
            });
            shapes.push(newCurves);
        });
        return shapes;
    };

    pasition.animate = function (option) {
        var pathA = pasition.path2shapes(option.from);
        var pathB = pasition.path2shapes(option.to);
        var pathArr = pasition._preprocessing(pathA, pathB);

        var beginTime = new Date(),
            end = option.end || function () {},
            progress = option.progress || function () {},
            begin = option.begin || function () {},
            easing = option.easing || function (v) {
                return v;
            },
            tickId = null,
            outShape = null,
            time = option.time;

        begin(pathA);

        var tick = function tick() {
            var dt = new Date() - beginTime;
            if (dt >= time) {
                outShape = pathB;
                progress(outShape, 1);
                end(outShape);
                cancelAnimationFrame(tickId);
                return;
            }
            var percent = easing(dt / time);
            outShape = pasition._lerp(pathArr[0], pathArr[1], percent);
            progress(outShape, percent);
            tickId = requestAnimationFrame(tick);
        };
        tick();
    };

    return pasition;

})));